package examples;

import java.util.concurrent.CountDownLatch;

/**
 * 1、定义CountDownLatch,初始化信号数目 2、调用await等待信号都执行了 3、调用countDown通知该进程完成了
 * 
 * 适用场景： 1、初始化的信号数目不可以更改 2、将一个任务分成若干线程执行，等到所有线程执行完，再进行汇总处理
 * 
 * 总结： CounDownLatch对于管理一组相关线程非常有用。上述示例代码中就形象地描述了两种使用情况。 第一种是计算器为1，代表了两种状态，开关。
 * 第二种是计数器为N，代表等待N个操作完成。
 * 
 * @author 10255_000
 * 
 */

public class CountDownLatchDemo {
	private static final int N = 10;

	public static void main(String[] args) throws InterruptedException {
		CountDownLatch doneSignal = new CountDownLatch(N);
		CountDownLatch startSignal = new CountDownLatch(1);

		for (int i = 1; i <= N; i++) {
			new Thread(new Worker(i, doneSignal, startSignal)).start();
		}

		System.out.println("begin------------");
		startSignal.countDown();
		doneSignal.await();
		System.out.println("Ok");
	}

	static class Worker implements Runnable {
		private final CountDownLatch doneSignal;
		private final CountDownLatch startSignal;
		private int beginIndex;

		Worker(int beginIndex, CountDownLatch doneSignal,
				CountDownLatch startSignal) {
			this.startSignal = startSignal;
			this.beginIndex = beginIndex;
			this.doneSignal = doneSignal;
		}

		@Override
		public void run() {
			try {
				startSignal.await();
				beginIndex = (beginIndex - 1) * 10 + 1;
				for (int i = beginIndex; i < beginIndex + 10; i++) {
					System.out.println(i);
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				doneSignal.countDown();
			}

		}

	}

}
